package com.yanqu.road.server.manger.activity.douluodalu;

import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.douluodalu.config.DouLuoDaLuConfig;
import com.yanqu.road.entity.activity.douluodalu.config.HideRewardDrawItem;
import com.yanqu.road.entity.activity.douluodalu.enums.eDouLuoDaLuBuffType;
import com.yanqu.road.entity.activity.douluodalu.log.PatronsBlood;
import com.yanqu.road.entity.activity.gourdchild.config.GourdMountainControl;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eShopType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogDouLuoDaLuPatronsFightResult;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.logic.activity.DouLuoDaLuLogic;
import com.yanqu.road.logic.bussiness.activity.DouLuoDaLuActivityBusiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.helper.UnionActivityGroupHelper;
import com.yanqu.road.logic.pb.DouLuoDaLuPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.douluodalu.DouLuoDaLuProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.douluodalu.DouLuoDaLuModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.config.GoodsBagMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.union.GameUnionActivityGroupMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.mina.util.ConcurrentHashSet;

import java.math.BigInteger;
import java.util.*;

public class DouLuoDaLuMgr extends TempMgr {

    static ActivityInfo activityInfo;

    static DouLuoDaLuConfig config;

    static Random random = new Random();

    //需要上传门客信息的玩家
    private static Set<Long> needUploadUserInfoSet = new ConcurrentHashSet<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    public static void reloadActivityData() {
        getLogger().info("reload DouLuoDaLu Activity start");
        ActivityInfo tempActivityInfo;
        List<ActivityInfo> openActivityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.DouLuoDaLuActivity.getValue());
        if (openActivityInfoList.isEmpty()) {
            activityInfo = null;
            config = null;
        }else {
            tempActivityInfo = openActivityInfoList.get(0);
            DouLuoDaLuConfig tempConfig = new DouLuoDaLuConfig();

            List<Integer> activityIdList = new ArrayList<>();
            activityIdList.add(tempActivityInfo.getActivityId());
            Map<String, ActivityConfig> activityConfigMap = ActivityBussiness.getActivityConfigMap(activityIdList).get(tempActivityInfo.getActivityId());

            //配置项
            DouLuoDaLuConfig.parseConfig(tempConfig, activityConfigMap, tempActivityInfo);

            tempConfig.setRegionInfoList(DouLuoDaLuActivityBusiness.getDouLuoDaLuRegionInfoList(tempActivityInfo.getActivityId()));
            tempConfig.setEventInfoList(DouLuoDaLuActivityBusiness.getDouLuoDaLuEventInfoList(tempActivityInfo.getActivityId()));
            DouLuoDaLuConfig.parseBoxOpenConsume(tempConfig);

            //现金商城礼包
            Map<Integer, MallInfo> mallInfoMap = NormalActivityMgr.getMallInfoTypeMap(tempActivityInfo.getActivityId(), eShopType.DouLuoDaLuActivityMoneyMall.getValue());
            for(MallInfo item : mallInfoMap.values()) {
                String[] str = item.getExtendParam().split("\\|");
                int type = Integer.valueOf(str[0]);
                int vip = Integer.valueOf(str[1]);
                Map<Integer,MallInfo> typeMap = tempConfig.getRmbMallInfoTypeMap().get(type);
                if(typeMap == null){
                    typeMap = new HashMap<>();
                    tempConfig.getRmbMallInfoTypeMap().put(type, typeMap);
                }
                typeMap.put(vip,item);
            }

            config = tempConfig;
            activityInfo = tempActivityInfo;
        }
        getLogger().info("reload DouLuoDaLu Activity finish");

        // 在线玩家下发数据
        for (GamePlayer gamePlayer : GamePlayerMgr.getAllOnlinePlayer()) {
            DouLuoDaLuModule module = gamePlayer.getModule(DouLuoDaLuModule.class);
            module.syncConfig();
            module.initUserData();
        }
    }

    /**
     * 是否玩家可以进入活动
     */
    public static int canEntryActivity(GamePlayer player) {
        if(!ActivityMgr.activityInShowTime(DouLuoDaLuMgr.getActivityInfo())){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_OPEN;
        }
        if(!SystemOpenMgr.systemOpen(player, eSystemId.DouLuoDaLuActivity.getValue())){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_UNLOCK;
        }

        int groupId = GameUnionActivityGroupMgr.getGroupId(DouLuoDaLuMgr.getActivityInfo().getActivityId(), player.getUserId());
        if (groupId == UnionActivityGroupHelper.NO_GROUP_ID) {
            return GameErrorCode.E_UNION_ACTIVITY_GROUP_NO_ABLE;
        }
        return 0;
    }

    /**
     * 判断是否是在组队期[beginTime,createTeamEndTime)
     */
    public static int activityInCreateTeamPeriod(){
//        return 0;
        if(activityInfo == null){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_CREATE_TEAM_TIME;
        }
        int now = DateHelper.getCurrentSecond();
        long createTeamEndTime = activityInfo.getBeginTime() + config.CREATE_TEAM_TIME * DateHelper.MINUTE_SECONDS;
        if( now < activityInfo.getBeginTime() || now >= createTeamEndTime){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_CREATE_TEAM_TIME;
        }
        return 0;
    }

    /**
     * 判断是否是在猎魂森林期[createTeamEndTime, [10点 - 19点) endTime)
     */
    public static int activityInLieHunPeriod(){
        if(activityInfo == null){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_LIE_HUN_TIME;
        }
        int now = DateHelper.getCurrentSecond();
        long createTeamEndTime = activityInfo.getBeginTime() + config.CREATE_TEAM_TIME * DateHelper.MINUTE_SECONDS;
        if(now < createTeamEndTime || now >= activityInfo.getEndTime()){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_LIE_HUN_TIME;
        }
        int hour = DateHelper.getHours();
        if(hour < config.FIGHT_DAILY_OPEN_TIME_1 || hour >= config.FIGHT_DAILY_END_TIME_1){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_LIE_HUN_TIME;
        }
        return 0;
    }

    /**
     * 判断是否是在魂师对决期[createTeamEndTime, [19点 - 22点) endTime)
     */
    public static int activityInDuiJuePeriod(){
        if(activityInfo == null){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_DUI_JUE_TIME;
        }
        int now = DateHelper.getCurrentSecond();
        long createTeamEndTime = activityInfo.getBeginTime() + config.CREATE_TEAM_TIME * DateHelper.MINUTE_SECONDS;
        if(now < createTeamEndTime || now >= activityInfo.getEndTime()){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_DUI_JUE_TIME;
        }
        int hour = DateHelper.getHours();
        if(hour < config.FIGHT_DAILY_OPEN_TIME_2 || hour >= config.FIGHT_DAILY_END_TIME_2){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_NO_IN_DUI_JUE_TIME;
        }
        return 0;
    }

    /**
     * 判断是否是在休息期[createTeamEndTime, [22点 - 10点) endTime)
     */
    public static int activityInRestPeriod(){
        if(activityInfo == null){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_IN_RESET_TIME;
        }
        int hour = DateHelper.getHours();
        if(hour >= config.FIGHT_DAILY_END_TIME_2 || hour < config.FIGHT_DAILY_OPEN_TIME_1){
            return 0;
        }
        return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_IN_RESET_TIME;
    }

    public static void unionChange(List<Long> syncUserIdList) {
        for(long uid : syncUserIdList){
            unionChange(uid);
        }
    }

    public static void unionChange(GamePlayer player) {
        addNeedUploadUserInfo(player);
    }

    public static void unionChange(long userId) {
        try{
            GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
            if(gamePlayer != null){
                addNeedUploadUserInfo(gamePlayer);
            }else {
                if(ActivityMgr.activityInShowTime(activityInfo)){

                }
            }
        }catch (Exception e){
            getLogger().error(e);
        }
    }

    public static void addNeedUploadUserInfo(GamePlayer player){
        try {
            if (DouLuoDaLuMgr.canEntryActivity(player) != 0) return;

            //if (DouLuoDaLuMgr.activityInRestPeriod() == 0) return;

            synchronized (needUploadUserInfoSet) {
                needUploadUserInfoSet.add(player.getUserId());
            }
        }catch (Exception e){
            getLogger().error(e);
        }
    }

    public static void clearUploadUserInfo(){
        if(needUploadUserInfoSet.size() > 0) {
            synchronized (needUploadUserInfoSet) {
                needUploadUserInfoSet.clear();
            }
        }
    }

    public static void uploadUserInfo(){
        List<Long> list = new ArrayList<>();
        synchronized (needUploadUserInfoSet) {
            Iterator<Long> iterator = needUploadUserInfoSet.iterator();
            while (iterator.hasNext()) {
                list.add(iterator.next());
            }
            needUploadUserInfoSet.clear();
        }
        if(list.size() > 0){
            List<GamePlayer> batch = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                GamePlayer player = GamePlayerMgr.getOnlinePlayer(list.get(i));
                if(player == null){
                    continue;
                }
                batch.add(player);
                if((i + 1) % 50 == 0) {
                    uploadUserInfo(batch);
                    batch = new ArrayList<>();
                }else if(i == list.size() - 1) {
                    uploadUserInfo(batch);
                }
            }
        }
    }

    public static void uploadUserInfo(List<GamePlayer> list) {
        if(list.size() == 0){
            return;
        }

        Map<Integer, DouLuoDaLuProto.DouLuoDaLuUploadUserDataMsg.Builder> uploadMap = new HashMap<>();

        long serverId = GameServer.getInstance().getServerId();
        for (GamePlayer player : list) {
            int groupId = GameUnionActivityGroupMgr.getGroupId(DouLuoDaLuMgr.getActivityInfo().getActivityId(), player.getUserId());
            DouLuoDaLuProto.DouLuoDaLuUploadUserDataMsg.Builder upload = uploadMap.get(groupId);
            if (upload == null) {
                upload = DouLuoDaLuProto.DouLuoDaLuUploadUserDataMsg.newBuilder();
                upload.setActivityId(DouLuoDaLuMgr.getActivityInfo().getActivityId());
                uploadMap.put(groupId, upload);
            }

            DouLuoDaLuProto.DouLuoDaLuUploadUserInfo.Builder infoBuilder = DouLuoDaLuProto.DouLuoDaLuUploadUserInfo.newBuilder();

            PatronsModule patronsModule = player.getModule(PatronsModule.class);
            infoBuilder.setPlayerInfo(PlayerBasePb.parsePlayerBaseTempMsg(UserMgr.getUserBaseInfo(player.getUserId(), serverId)));
            // 门客总赚钱值
            infoBuilder.setAllPatronsEarn(patronsModule.getTotalPatronsAbility().longValue());
            infoBuilder.addAllAllPatrons(DouLuoDaLuMgr.getAllPatronsBuilder(player));
            infoBuilder.setUserId(player.getUserId());
            upload.addUserInfo(infoBuilder);
        }

        for (Map.Entry<Integer, DouLuoDaLuProto.DouLuoDaLuUploadUserDataMsg.Builder> entry : uploadMap.entrySet()) {
            int groupId = entry.getKey();
            DouLuoDaLuProto.DouLuoDaLuUploadUserDataMsg.Builder upload = entry.getValue();
            GamePlayerMgr.sendUnionActivityGroupPacket(Protocol.C_DOU_LUO_DA_LU_UPLOAD_USER_DATA, upload,0, upload.getActivityId(), groupId);
        }
    }

    public static void handleGoodsBuff(List<Integer> buffIdList, DouLuoDaLuConfig config, Property boxReward, GoodsInfo goodsInfo) {
        OpenGoodsBagResult openResult = GoodsBagMgr.getRandomGoods(goodsInfo.getGoodsId());
        if (buffIdList.contains(eDouLuoDaLuBuffType.GOODS_BUFF.getId())) {
            for (Map.Entry<Integer, BigInteger> integerEntry : openResult.getReward().getGoods().entrySet()) {
                long v = DouLuoDaLuLogic.calBuff(integerEntry.getValue().longValue(), eDouLuoDaLuBuffType.GOODS_BUFF, config);
                boxReward.addProperty(integerEntry.getKey(), BigInteger.valueOf(v));
            }
        } else {
            boxReward.addProperty(openResult.getReward());
        }
    }

    public static void handleGoodsBuff(List<Integer> buffIdList, DouLuoDaLuConfig config, Property boxReward, String reward) {
        if (buffIdList.contains(eDouLuoDaLuBuffType.GOODS_BUFF.getId())) {
            for (Map.Entry<Integer, BigInteger> integerEntry : PropertyHelper.parseStringToProperty(reward).getGoods().entrySet()) {
                long v = DouLuoDaLuLogic.calBuff(integerEntry.getValue().longValue(), eDouLuoDaLuBuffType.GOODS_BUFF, config);
                boxReward.addProperty(integerEntry.getKey(), BigInteger.valueOf(v));
            }
        } else {
            boxReward.addProperty(PropertyHelper.parseStringToProperty(reward));
        }
    }

    /**
     * 获取隐藏款
     */
    public static HideRewardDrawItem getHideRewardDrawItem(List<HideRewardDrawItem> configItemList) {
        List<Integer> weightList = new ArrayList<>();
        // 待抽取集合
        List<HideRewardDrawItem> itemList = new ArrayList<>();
        for (HideRewardDrawItem itemConfig : configItemList) {
            if(!itemConfig.isHide()){
                continue;
            }
            weightList.add(itemConfig.getWeight());
            itemList.add(itemConfig);
        }
        // 抽
        int index = RandomHelper.getRandomIndexByWeight(weightList, random);
        return itemList.get(index);
    }

    /**
     * 获取保底需要满足几个不同的奖励
     */
    private static int getDistinctCount(DouLuoDaLuConfig config, int totalTimes){
        int count = 0;
        for (int i = 0; i < config.getControlList().size(); i++) {
            GourdMountainControl control = config.getControlList().get(i);
            if(totalTimes >= control.getTimes()){
                count = control.getDistinct();
            }
        }
        return count;
    }

    /**
     * 正常抽
     */
    public static HideRewardDrawItem getHideRewardDrawItem(DouLuoDaLuConfig config, int commonTimes, int totalTimes, List<Integer> drawBoxList, boolean excludeHide, long userId) {
        // 正常抽取
        // 获取权重
        List<HideRewardDrawItem> configList = config.getDrawItemList();
        int additionWeight = 0;
        int addWeightMinTimes = config.getAdditionParam().get(0);
        if(commonTimes > addWeightMinTimes){
            additionWeight += config.getAdditionParam().get(1) * (commonTimes - addWeightMinTimes);
            DouLuoDaLuMgr.getLogger().debug("----------user {} 隐藏款加成 {}", userId, additionWeight);
        }
        // 已上次抽中的奖品
        Set<Integer> itemSet = new HashSet<>();
        // 最后一次的奖品
        int lastItem = 0;
        if(drawBoxList.size() > 0){
            lastItem = drawBoxList.get(drawBoxList.size() - 1);
        }
        for (int itemId : drawBoxList) {
            itemSet.add(itemId);
        }
        // 是否触发新奖励
        int totalCount = itemSet.size();
        int count = getDistinctCount(config, totalTimes);
        List<Integer> weightList = new ArrayList<>();
        // 待抽取集合
        List<HideRewardDrawItem> itemList = new ArrayList<>();
        for (HideRewardDrawItem itemConfig : configList) {
            // 保底，需扣除已获得
            if(count > totalCount){
                if(itemSet.contains(itemConfig.getItemId())){
                    continue;
                }
            }
            //是否与上次重复奖励
            if(lastItem == itemConfig.getItemId()){
                continue;
            }
            // 隐藏大奖
            if (excludeHide && itemConfig.isHide()){
                continue;
            }
            if (itemConfig.isHide()) {
                // 隐藏款加成
                weightList.add(itemConfig.getWeight() + additionWeight);
            } else {
                weightList.add(itemConfig.getWeight());
            }
            itemList.add(itemConfig);
        }
        // 抽
        int index = RandomHelper.getRandomIndexByWeight(weightList, random);
        return itemList.get(index);
    }


    /**
     * 检查队名合法性
     * @param name
     * @return
     */
    public static short checkTeamName(String name){
        if(StringUtils.isNullOrEmpty(name)){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_TEAM_NAME_NO_EMPTY;
        }
        int nameLength = StringUtils.getStringLen(name);
        if(nameLength > config.TEAM_NAME_LENGTH_LIMIT){
            return GameErrorCode.E_NAME_LENGTH_OVER;
        }
        //敏感字过滤
        if(ForbiddenWordMgr.isNickNameForbidden(name)){
            return GameErrorCode.E_DOU_LUO_DA_LU_ACTIVITY_TEAM_NAME_FORBIDDEN;
        }
        return 0;
    }

    public static void addPatronsBattleSettleLog(GamePlayer player, DouLuoDaLuProto.DouLuoDaLuBattleSettleLog logBuild, DouLuoDaLuProto.DouLuoDaLuBattleSettlementTem settle, boolean oneKey) {
        int teamId = player.getModule(DouLuoDaLuModule.class).teamId;
        //日志
        List<PatronsBlood> patronsBloodList = new ArrayList<>();
        for (DouLuoDaLuProto.DouLuoDaLuBattlePatronsBlood battlePatronsBlood : logBuild.getPatronsList()) {
            patronsBloodList.add(DouLuoDaLuPb.parseDouLuoDaLuPatronsBlood(battlePatronsBlood));
        }
        LogDouLuoDaLuPatronsFightResult log = new LogDouLuoDaLuPatronsFightResult(DouLuoDaLuMgr.getActivityInfo().getActivityId(), player.getUserId(), teamId, logBuild.getMyScore(), settle.getPatronsId(), logBuild.getHunLi(),
                oneKey, logBuild.getBuffList(), settle.getBattleType(), logBuild.getEnemyUserId(), logBuild.getEnemyServerId(), logBuild.getEnemyScore(), logBuild.getEnemyPatronsNum(), logBuild.getEnemyHunLi(),
                settle.getAllKill(), logBuild.getWinTimes(), settle.getAllRewards(), patronsBloodList, settle.getAllPatronsExp());
        if(oneKey){
            //补充一键之前的奖励
            if(logBuild.hasOldPatronsExp()){
                log.setAllPatronsExp(log.getAllPatronsExp() + logBuild.getOldPatronsExp());
            }
            if(logBuild.hasOldRewards()){
                Property allRewards = PropertyHelper.parseStringToProperty(log.getRewards());
                allRewards.addProperty(PropertyHelper.parseStringToProperty(logBuild.getOldRewards()));
                log.setRewards(PropertyHelper.parsePropertyToString(allRewards));
            }
        }
        AutoLogMgr.add(log);
    }

    public static List<DouLuoDaLuProto.DouLuoDaLuPatronsDataTemp> getAllPatronsBuilder(GamePlayer player) {
        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        List<DouLuoDaLuProto.DouLuoDaLuPatronsDataTemp> list = new ArrayList<>();
        for (Map.Entry<Integer, UserPatrons> patronsEntry : patronsModule.getUserPatronsMap().entrySet()) {
            UserPatrons userPatrons = patronsEntry.getValue();
            DouLuoDaLuProto.DouLuoDaLuPatronsDataTemp.Builder builder = DouLuoDaLuProto.DouLuoDaLuPatronsDataTemp.newBuilder();
            builder.setPatronsId(userPatrons.getPatronsId());
            builder.setPatronsLv(userPatrons.getLevel());
            builder.setAbility(userPatrons.getAbility().longValue());
            builder.setSkinId(userPatrons.getSkinId());
            builder.setPromotionId(userPatrons.getShowPromotionId());
            builder.setStageLv(userPatrons.getStageLv());
            list.add(builder.build());
        }
        return list;
    }

    public static ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public static DouLuoDaLuConfig getConfig() {
        return config;
    }
}
